When using regular expressions, a capturing group provides extra information about the matched pattern. Named groups will store the matched
contents on the groups
property of the returned matches.
const regex = /(?<month>[0-9]{2})\/(?<year>[0-9]{2})/;
const { groups: {month, year} } = regex.exec("01/02"); // month is '01', year is '02'
This rule raises issues in several cases:
- Named groups are defined but never called by their name. To make the code more readable, remove unused named capturing groups.
const score = "14:1";
const scorePattern = /(?<player1>[0-9]+):(?<player2>[0-9]+)/; // Noncompliant - named groups are never used
if (scorePattern.exec(score)) {
checkScore(score);
}
- Named groups are defined but called by their index. To make the code more readable:
- access the matched contents using the named group; or
- remove it from the pattern.
const datePattern = /(?<month>[0-9]{2})/(?<year>[0-9]{2})/;
const dateMatcher = datePattern.exec("01/02");
if (dateMatcher) {
checkValidity(dateMatcher[1], dateMatcher[2]); // Noncompliant - group indexes are used instead of names
}
- Named groups are referenced while not defined. This can have undesired effects, as it will return
undefined
if there are other
named groups. If there are none, groups
will be undefined
, and trying to access the named group will throw a
TypeError
if its existence has not been checked.
const datePattern = /(?<month>[0-9]{2})/(?<year>[0-9]{2})/;
const dateMatcher = datePattern.exec("01/02");
if (dateMatcher) {
checkValidity(dateMatcher.groups.day); // Noncompliant - there is no group called "day", returns `undefined`
}